/*
深拷贝：只是针对Object 和 Array这样的引用数据类型的。
深拷贝会另外创造一个一模一样的对象，新对象跟原对象不共享内存，修改新对象不会改到原对象，是“值”而不是“引用”（不是分支）

总的来说，实现深拷贝的流程
1：需要判断传来的类型
2：对数值和对象数据，进行递归创建新对象或数组
3：对于
 */
// 遍历实现
const deepclone = (target, map = new WeakMap()) =>{
    // 基本类型直接返回 深拷贝只针对Object 和 Array这样的引用数据类型的
    if(typeof target !== 'object' || target === null) return target;
    // 函数 正则 日期 ES6新对象， 执行构造函数
    // 拿到对象的构造函数
    const constructor = target.constructor;
    // 这个正则表达式用于检测变量  constructor  所指向的函数是不是 JavaScript 内置的类对象
    if (/^(Function|RegExp|Date|Map|Set)$/i.test(constructor.name)) return new constructor(target);
    // map 标记每一个出现过的属性，避免循环引用
    if(map.get(target)) return map.get(target);
    map.set(target, true);
    const cloneTarget = Array.isArray(target) ? [] : {};
    for(const prop in target){
        cloneTarget[prop] = deepclone(target[prop], map);
    }
    return cloneTarget;
}
// 递归实现  这个好理解些哦
function deepCopy(obj) {
    // 确定需要复制的对象类型
    const type = Object.prototype.toString.call(obj).slice(8, -1);

    // 根据类型进行处理
    switch (type) {
        case "Object":
            const newObj = {};
            for (let key in obj) {
                newObj[key] = deepCopy(obj[key]);
            }
            return newObj;

        case "Array":
            const newArr = [];
            for (let i = 0; i < obj.length; i++) {
                newArr.push(deepCopy(obj[i]));
            }
            return newArr;

        case "Date":
            return new Date(obj.getTime());

        case "RegExp":
            return new RegExp(obj);
// 返回其他 包括map set 基本数据类型
        default:
            return obj;
    }
}

let a = {
    a:1
}
let test = {
    map: new Map([['key1', 'value1'], ['key2', 'value2'], [a, a]]),
    set: new Set([a]),
    obj: {a:1},
    arr: [1,2,3],
    date: new Date(),
    reg: /^(Function|RegExp|Date|Map|Set)$/g
}
let result = deepCopy(test)
a.a=3
// 每个对象都有一个  constructor  属性，用于指向创建该对象的构造函数。这个属性指向构造函数本身，而不是构造函数的实例
// console.log('这是啥',test.constructor(test))
console.log(result)
